import 'package:get/get.dart';
import 'package:get/get_state_manager/src/simple/get_controllers.dart';
import 'package:tot_android_flutter/common/ext/get_ext.dart';
import 'package:tot_android_flutter/eneity/AppResponse.dart';
import 'package:tot_android_flutter/network/api.dart';
import 'package:tot_android_flutter/network/api_service.dart';
import 'package:tot_android_flutter/utils/ToastUtil.dart';
import 'package:tot_android_flutter/utils/log_util.dart';

import '../common/widget/state/LoadingStatus.dart';
import '../common/widget/state/view_state.dart';
import '../network/exception/request_exception.dart';
import 'package:flutter/cupertino.dart';

typedef JudgeEmpty<T> = bool Function(T? value);
typedef JudgeNoMoreData<T> = bool Function(T? value);

abstract class BaseController extends GetxController {
  final Rx<ViewState> viewState = ViewState().obs;
  final ApiService apiService = ApiService.instance;


  void loadData();

  void sendRequest<T>(
    Future<AppResponse<T>> sendRequestBlock, {
    bool bindViewState = true,
    bool showLoadingDialog = false,
    bool needLogin = false,
    bool emptyAsSuccess = false,
    JudgeEmpty<T>? judgeEmptyCallback,
    ValueChanged<T>? successCallback,
    VoidCallback? emptyCallback,
    ValueChanged<RequestException>? failCallback,
  }) {
    if (bindViewState) {
      viewState.value = ViewStateLoading();
    }
    if (showLoadingDialog) {
      Get.showLoading();
    }
    sendRequestBlock.then((result) {
      if (result.isSuccess()) {
        if (showLoadingDialog) {
          Get.hideLoading();
        }
        bool isEmpty = (judgeEmptyCallback != null)
            ? judgeEmptyCallback(result.data)
            : result.isEmpty();

        if (!isEmpty || (emptyAsSuccess && isEmpty)) {
          if (successCallback != null) {
            successCallback(result.data);
          }
          if (bindViewState) {
            viewState.value = ViewStateSuccess();
          }
        } else {
          if (bindViewState) {
            viewState.value = ViewStateEmpty();
          }
          if (emptyCallback != null) {
            emptyCallback();
          }
        }
      } else {
        RequestException requestException = RequestException.createfromMessage(result.msg,result.code);
        if (bindViewState) {
          viewState.value = ViewStateFail(requestException.code, requestException.message);
        }
        if (showLoadingDialog) {
          Get.hideLoading();
          showToast(requestException.toString());
        }
        if (failCallback != null) {
          failCallback(requestException);
        }
      }
    }).catchError((e, staceTrace) {
      RequestException requestException = RequestException.create(e);
      if (bindViewState) {
        viewState.value =
            ViewStateError(requestException.code, requestException.message);
      }
      if (showLoadingDialog) {
        Get.hideLoading();
        showToast(requestException.toString());
      }
      if (failCallback != null) {
        failCallback(requestException);
      }
      WanLog.e("sendRequest catchError====>error:$e, staceTrace:$staceTrace}");
    });
  }

  void sendRequestFun(
    Future<void> Function() sendRequestBlock, {
    bool bindViewState = false,
    bool showLoadingDialog = false,
    VoidCallback? emptyCallback,
        ValueChanged<RequestException>? failCallback,
  }) {
    if (bindViewState) {
      viewState.value = ViewStateLoading();
    }
    if (showLoadingDialog) {
      Get.showLoading();
    }
    sendRequestBlock().then((_) {
      if (showLoadingDialog) {
        Get.hideLoading();
      }
      if (bindViewState) {
        viewState.value = ViewStateSuccess();
      }
    }).catchError((e, staceTrace) {

      if (e is RequestException) {
        if ((e).code == RequestException.APP_CODE_EMPTY_DATA) {
          if (bindViewState) {
            viewState.value = ViewStateEmpty();
          }
          if (emptyCallback != null) {
            emptyCallback();
          }
          return;
        }
      }

      RequestException requestException = RequestException.create(e);
      if (bindViewState) {
        viewState.value =
            ViewStateError(requestException.code, requestException.message);
      }
      if (showLoadingDialog) {
        Get.hideLoading();
        showToast(requestException.toString());
      }
      if (failCallback != null) {
        failCallback(requestException);
      }
      WanLog.e("sendRequest catchError====>error:$e, staceTrace:$staceTrace}");
    });
  }

  void showToast(String msg) {
    ToastUtil.showToast(msg);
  }
}
